package com.deke.auth.config;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.deke.auth.filter.JwtVerifyFilter;
import com.deke.auth.service.MyUserService;
import com.deke.utils.JwtTool;
import com.deke.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/*
 * @author     ：Username 刘亦辰（59372312@qq.com）
 * @date       ：Created in 2022/11/30 21:20
 * @description：
 * @modified By：
 * @version:
 */

@Component
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    //重写父类的两个方法
    @Autowired
    private MyUserService userService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtVerifyFilter jwtVerifyFilter;


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //设置前置过滤器
        http.addFilterBefore(jwtVerifyFilter, UsernamePasswordAuthenticationFilter.class);
        //设置登录表单
        http.formLogin()
                //登录成功执行函数
                .successHandler(successHandler())
                //登录失败执行函数
                .failureHandler(failureHandler())
                .permitAll();
        //设置security允许登录跨域
        http.cors();
        //关闭跨域伪造
        http.csrf().disable();
        //其他任何请求都需要认证
        http.authorizeRequests().anyRequest().authenticated();
        //无权限处理
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //忽略doc。html路径
        web.ignoring().mvcMatchers("/doc.html");
    }

    /**
    * @create by: Username 刘亦辰 
    * @description: 登录成功方法   
    * @create time: 2022/11/30 21:29
    * @param null
    * @return :  AuthenticationFailureHandler
    **/

    private AuthenticationSuccessHandler successHandler(){
        return (request,response,authentication)->{
            //设置相应编码
            response.setContentType("application/json;charset=utf-8");
            //拿到输出对象
            PrintWriter writer = response.getWriter();
            Map<String,Object> map = new HashMap<>();
            //获取登录成功后的用户对象
            User user = (User) authentication.getPrincipal();
            //拿到用户名并封装
            String username = user.getUsername();
            map.put("username",username);
            //拿到用户权限并转为字符串封装
            Collection<GrantedAuthority> authorities = user.getAuthorities();
            //stream流的方式转成string类型
            List<String> permissions = authorities.stream()
                    .filter(item->item.getAuthority()!=null)
                    .map(item->item.getAuthority())
                    .collect(Collectors.toList());
            map.put("permissions",permissions);
            //按照用户名和权限 生成 token
            String token = JwtTool.createJWT(map);
            Result result = new Result(2000,"登录成功",token);
            String jsonString = JSON.toJSONString(result);
            writer.println(jsonString);
            writer.flush();
            writer.close();
        };
    }

    /*
    * @create by: Username 刘亦辰 
    * @description: 登录失败的方法 
    * @create time: 2022/11/30 21:30
    * @param null
    * @return :  AuthenticationFailureHandler
    */

    private AuthenticationFailureHandler failureHandler(){
        return (requset,response,e)->{
            //设置相应编码
            response.setContentType("application/json;charset=utf-8");
            //拿到输出对象
            PrintWriter writer = response.getWriter();
            Result result = new Result(5000,"账号密码错误");
            //将实体类转换成json字符串
            String jsonString = JSON.toJSONString(result);
            //输出
            writer.println(jsonString);
            //刷新输出对象
            writer.flush();
            //释放输出对象
            writer.close();
        };
    }

    /**
     * @create by: Username 刘亦辰 
     * @description: 无权限处理方法 
     * @create time: 2022/12/2 10:22
     * @param null
     * @return :  AuthenticationFailureHandler
     **/
    private AccessDeniedHandler accessDeniedHandler(){
        return ((request,response,Authentication)->{
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();
            Result result = new Result(4003,"权限不足");
            //把java对象转换为json字符串。---
            String jsonStr = JSONUtil.toJsonStr(result);
            writer.print(jsonStr);
            writer.flush();
            writer.close();
        });
    }
}